package com.iot08.api.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iot08.api.service.supplement.KafkaService;
import com.iot08.api.utils.wxpay.NewXMLUtil;
import com.iot08.api.utils.wxpay.XMLUtil;
import com.iot08.common.entity.app.DeviceSanWord;
import com.iot08.common.entity.app.HCYAuth;
import com.iot08.common.entity.app.Device;
import com.iot08.common.service.base.BaseService;
import com.iot08.common.utils.DateUtil;
import com.iot08.common.utils.HttpReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 云词本授权
 * @author weichao 1299101858@qq.com
 * @version 1.0
 * @date 12/16/22 6:37 PM
 */
@Slf4j
@Service
public class HCYAuthService extends BaseService<HCYAuth> {

//    public String HCY_IOS_CHANNELID = "10004";
//    public String HCY_Android_CHANNELID = "10003";
//    public String HCY_Web_CHANNELID = "10002";

    //默认提前一天检查
    @Value("${hcy.checkTokenExpiryTime:86400}")
    public Integer checkTokenExpiryTime;

    /**
     * 和彩云 的配置列表
     */
    @Value("${hcy.configList:[]}")
    public String HCY_ConfigArrStr;
    public JSONArray HCY_ConfigArr;


    //1.2.3刷新Token oauth2/refreshToken
    public String HCYRefreshTokenURL = "https://miniapp.yun.139.com/open-mpplatform/oauth2/refreshToken";

    //1.4.1中间页接入方式获取用户凭证oauth2/accessToken1
    public String HCYMiddlePageGetTokenURL = "https://miniapp.yun.139.com/open-mpplatform/oauth2/accessToken1";

    //授权中间页地址
    public String HCYMiddlePageURL = "https://miniapp.yun.139.com/middle/index.html#/middlePage";
//    public String HCYMiddlePageURL = "https://dicapitest.kidxin.com/hcy/middle/index.html#/middlePage";

    /**
     * 云盘-获取能力应用目录id
     */
    public String HCYgetAppFileIdURL = "http://miniapp.yun.139.com/richlifeApp/devapp/getAppFileId";

    /**
     * 云盘-查询个人云文件列表
     */
    public String HCYgetdiskURL = "https://miniapp.yun.139.com/richlifeApp/devapp/getdisk";
    /**
     * 创建限定目录下子目录 创建目录
     */
    public String HCYcreateCatalogExtURL = "https://miniapp.yun.139.com/richlifeApp/devapp/createCatalogExt";

    /**
     * 云盘-上传文件(第一阶段:拿到上传URL+特定信息, 第二阶段:根据信息+url 上传)
     */
    public String HCYuploadFileURL = "https://miniapp.yun.139.com/richlifeApp/devapp/pcUploadFileRequest";
    /**
     * 云盘-下载文件 (拿到下载URL 再下载)
     */
    public String HCYdownloadFileURL = "https://miniapp.yun.139.com/richlifeApp/devapp/downloadRequest";

    /**
     * getServiceDiskInfoV2 查询用户空间信息
     */
    public String HCYgetServiceDiskInfoV2URL = "https://miniapp.yun.139.com/richlifeApp/devapp/getServiceDiskInfoV2";

    // 后台代替设备访问授权页后的 请求验证码接口:
    public String HCYGetVcodeURL = "https://miniapp.yun.139.com/open-mpplatform/oauth2/getDyncPasswd1";

    // 后台代替设备请求验证码后, 提交验证码接口:
    public String HCYPostVcodeURL = "https://miniapp.yun.139.com/open-mpplatform/oauth2/verifyDyncPasswd1";


    //正式服
    public String HCYAuthBackTemp_H5URL = "https://api.tx.kidxin.com/getway/dicpen/hcyTempPage";

    //测试服
    public String DevHCYAuthBackTemp_H5URL = "https://apitest.tx.kidxin.com/getway/dicpen/hcyTempPage";


    /*
    终端类型	渠道id
    H5	10001
    WEB	10002
    APP(安卓)	10003
    APP（IOS）	10004
    微信服务号	10007
    其它（某些无法区分接入类型）	10009
    大屏（TV等）	10010
    小程序（微信，阿里，百度等）	10011
    硬件类型	10012
    */
    public String HCYChannelId = "10012";

    public JSONArray getHCY_ConfigArr() {
        if(HCY_ConfigArr == null){
            HCY_ConfigArr = JSONArray.parseArray(HCY_ConfigArrStr);
        }
        return HCY_ConfigArr;
    }


    public String getAppID(HCYAuth hcyAuth) {
        JSONObject item = this.getHCY_ConfigArr().getJSONObject(hcyAuth.getProject_type());
        return item.getString("appId");
//        if (hcyAuth.getProject_type() == 0) {
//            return this.HCY_NIUMAN_APPID;
//        } else {
//            return this.HCY_XXX_APPID;
//        }
    }

    public String getAppKey(HCYAuth hcyAuth) {
        JSONObject item = this.getHCY_ConfigArr().getJSONObject(hcyAuth.getProject_type());
        return item.getString("appKey");
    }

    public String getAppSecret(HCYAuth hcyAuth) {
        JSONObject item = this.getHCY_ConfigArr().getJSONObject(hcyAuth.getProject_type());
        return item.getString("appSecret");
    }

    public String getAppTitle(HCYAuth hcyAuth) {
        JSONObject item = this.getHCY_ConfigArr().getJSONObject(hcyAuth.getProject_type());
        return item.getString("ident");
    }

    /**
     * 用户授权成功后 换取 token
     * @param authUUID
     * @return
     */
    public String getAccesstokenWithUUID(HCYAuth authOB, String authUUID){
        //提交验证码成功 后这时候 用去请求才能获得token
        JSONObject getTokenParam = new JSONObject();
        getTokenParam.put("uuid", authUUID);
        String getTokenRes = HttpReq.sendPostJson(HCYMiddlePageGetTokenURL, getTokenParam.toJSONString());
        JSONObject getTokenResOB = JSONObject.parseObject(getTokenRes);
        Long nowTime = DateUtil.nowTimestampToLong();
        if(getTokenResOB.getInteger("code") == 0) {
            /*
            {
                "code": 0,
                "message": "成功",
                "data": {
                    "accessToken": "123",
                    "expiresIn": 168
                }
            }
            */
            JSONObject data = getTokenResOB.getJSONObject("data");
            String newToken = data.getString("accessToken");
            Long newTokenExpiresIn = nowTime + data.getInteger("expiresIn") * 3600;
            authOB.setAccesstoken(newToken);
            authOB.setAccesstoken_expiry(newTokenExpiresIn);
            authOB.setAccesstoken_update(new Date());
            authOB.setUpdateDate(new Date());
            this.save(authOB);
            return newToken;
        }else{
            log.error("openid:{} 请求移动云盘 token失败 getTokenResOB:{}", authOB.getId(), getTokenResOB);
        }
        return null;
    }


    public String refreshTokenWithAuth(HCYAuth authOB){
        Long nowTime = DateUtil.nowTimestampToLong();
        if ((authOB.getAccesstoken_expiry() - nowTime) < this.checkTokenExpiryTime) {
            //还在token有效期内, 只需更新即可.

            //刷新token的参数
            JSONObject refreshTokenParam = new JSONObject();
            refreshTokenParam.put("appId", this.getAppID(authOB));
            refreshTokenParam.put("appSecret", this.getAppSecret(authOB));
            refreshTokenParam.put("refreshToken", authOB.getAccesstoken());
            String refreshTokenRes = HttpReq.sendPostJson(this.HCYRefreshTokenURL, refreshTokenParam.toJSONString());
            JSONObject refreshTokenResOB = JSONObject.parseObject(refreshTokenRes);
            if (refreshTokenResOB.getInteger("code") == 0) {
                log.info("openid:{} 更新移动云盘 token成功 refreshTokenParam:{}  refreshTokenRes:{}", authOB.getId(), refreshTokenParam, refreshTokenRes);
                /*
                {
                    "code": 0,
                    "message": "成功",
                    "data": {
                        "accessToken": "123",
                        "expiresIn": 168
                    }
                }
                */
                JSONObject data = refreshTokenResOB.getJSONObject("data");
                String newToken = data.getString("accessToken");
                Long newTokenExpiresIn = nowTime + data.getInteger("expiresIn") * 3600;
                authOB.setAccesstoken(newToken);
                authOB.setAccesstoken_expiry(newTokenExpiresIn);
                authOB.setAccesstoken_update(new Date());
                authOB.setUpdateDate(new Date());
                this.save(authOB);
                return newToken;
            }else{
                log.error("openid:{} 更新移动云盘 token失败 refreshTokenParam:{}  refreshTokenRes:{}", authOB.getId(), refreshTokenParam, refreshTokenRes);;
            }
        }else{
            return authOB.getAccesstoken();
        }
        return null;

    }

    /**
     * 获取一下 用户的空间.
     * @param authOB
     * @return
     */
    public Object getServiceDiskInfo(HCYAuth authOB){

        return getHCYAPICommonFun(authOB, HCYgetServiceDiskInfoV2URL, null, false);
    }

    /**
     * 上传云单词
     * @param deviceSanWordList
     * @param hcyAuth
     * @param type 类型 1:生词本 2:扫描本
     * @return
     */
    public boolean uploadWord(JSONArray deviceSanWordList, HCYAuth hcyAuth, int type, String openid){
        String fileName = DeviceSanWordService.newWordsNotebookName;
        switch (type){
            case 1:
                fileName = DeviceSanWordService.newWordsNotebookName;
                break;
            case 2:
                fileName = DeviceSanWordService.scanWordNotebookName;
                break;
        }
        boolean haveAppFileId = true;
        if (hcyAuth.getAppCatalogID() == null){
            //不存在的情况下才重新获取, 如果目录已被删除 (操作 中国移动云盘APP等操作删除了 目录) 会报错误码 9149
            // 报错误码的情况下会清除 hcyAuth 的 appCatalogID 属性
            haveAppFileId = getAppFileId(hcyAuth);
        }

        JSONObject downloadFile = new JSONObject();

        if (haveAppFileId) {
            if(type == 1){
                //生词本
                if(hcyAuth.getContentID() == null){
                    //不存在的情况下才重新获取,如果内容文件已被删除 (操作 中国移动云盘APP等操作删除了 文件) 会报错误码 9149
                    // 报错误码的情况下会清除 hcyAuth 的 contentID 属性
                /*
                <?xml version="1.0" encoding="UTF-8"?>
                <result  resultCode="9149" desc="[501248|33E172FFBAE64B43B3F021A7CF1E52BB]Failed to invoke the service.The content[1Q11diXl808e06920231202110809dbk] does not exist in ND.[NDA(100572)][Flag:33E172FFBAE64B43B3F021A7CF1E52BB]">
                </result>
                */
                    getDisk(hcyAuth);
                }
            } else if (type == 2) {
                //扫描本
                if(hcyAuth.getScanContentID() == null){
                    //不存在的情况下才重新获取,如果内容文件已被删除 (操作 中国移动云盘APP等操作删除了 文件) 会报错误码 9149
                    // 报错误码的情况下会清除 hcyAuth 的 scanContentID 属性
                /*
                <?xml version="1.0" encoding="UTF-8"?>
                <result  resultCode="9149" desc="[501248|33E172FFBAE64B43B3F021A7CF1E52BB]Failed to invoke the service.The content[1Q11diXl808e06920231202110809dbk] does not exist in ND.[NDA(100572)][Flag:33E172FFBAE64B43B3F021A7CF1E52BB]">
                </result>
                */
                    getDisk(hcyAuth);
                }
            } else {
                //暂不支持版本
                log.info("暂不支持版本 type:{}", type);
                return false;
            }

            //判断如果有文件,需要下载后 读取增加后再上传
            String contentID = hcyAuth.getContentID();
            if(type == 2){
                contentID = hcyAuth.getScanContentID();
            }



            if (contentID != null) {
                downloadFile = getDownloadFile(hcyAuth, contentID, type);
                if (downloadFile == null) {
                    log.info("下载之前旧文件 失败 openid:{} contentID:{} type:{} (1:生词本 2:扫描本)", openid, contentID, type);
                    return false;
                }
            /*
            云盘文件内容 xxx.json
            {
                "862027050034552&6864f389d9876436bc8778ff071d1b6c":{
                    "type":1,
                    "srcText":"原文",
                    "transText":"译文",
                    "time":"20230505093823"
                },
                ...
            }
            * */
            }
        }else{
            //应用目录都没有的直接上传
        }


        for (int i = 0; i < deviceSanWordList.size(); i++) {
            DeviceSanWord deviceSanWord = deviceSanWordList.getObject(i, DeviceSanWord.class);
            JSONObject itemOB = new JSONObject();
            itemOB.put("id",deviceSanWord.getId());
            itemOB.put("type",deviceSanWord.getType());
            itemOB.put("srcText",deviceSanWord.getSrcText());
            itemOB.put("transText",deviceSanWord.getTransText());
            itemOB.put("time",deviceSanWord.getTime()); //扫描笔记录时间
            itemOB.put("modifytime",deviceSanWord.getModifytime().getTime()); //上次的修改时间
            downloadFile.put(deviceSanWord.getId(), itemOB);
        }

        //保存成数据流上传云盘

        boolean isUploadSuccess = uploadFileWithObject(hcyAuth, downloadFile.toJSONString(), fileName, type);
        if (isUploadSuccess) {
            log.info("上传单词成功openid:{} 单词列表:{}", openid, deviceSanWordList.toJSONString() );
            return true;
        }
        log.info("上传单词失败 openid:{} 单词列表:{}", openid, deviceSanWordList.toJSONString() );
        return false;
    }


    //获取能力应用目录id (会更新记录到数据库)
    public boolean getAppFileId(HCYAuth hcyAuth){
        JSONObject res = null;
        Object tempRes = getHCYAPICommonFun(hcyAuth, HCYgetAppFileIdURL, "{\"type\":\"1\"}", false);
        if (checkRes(tempRes, hcyAuth)) {
            res = (JSONObject) tempRes;
        }else{
            log.error("获取 能力应用目录id 失败 tempRes: {} openid:{}", tempRes, hcyAuth.getId());
            return false;
        }
        /*
        如果没有创建过应用目录会返回:
        {
            "code": 0,
            "data": {
                "exist":false
            },
            "message": "成功",
            "totalRows": 0
        }

        创建过正常返回
        {
            "code": 0,
            "data": {
                "appFileId": "0Q11diXl808e03120231129161650n16",
                "appFileName": "纽曼词典笔",
                "exist": true
            },
            "message": "成功",
            "totalRows": 0
        }
        */
        JSONObject data = res.getJSONObject("data");
        if(data != null) {
            Boolean exist = data.getBoolean("exist");
            if(exist){
                String appFileId = data.getString("appFileId");
                hcyAuth.setAppCatalogID(appFileId);
                hcyAuth = this.save(hcyAuth);
                log.info("保存 data:{} appFileId: {} 能力应用目录id 成功 openid:{}",data, appFileId, hcyAuth.getId());
            }else{
                log.info("能力应用目录 不存在 openid:{}", hcyAuth.getId());
                return false;
            }

        }else{
            log.info("保存 能力应用目录id 失败 res: {} openid:{}", res, hcyAuth.getId());
        }
        return false;
    }


    // 查询个人云文件列表  (会更新记录到数据库)
    public void getDisk(HCYAuth hcyAuth){
        JSONObject param = new JSONObject();
        JSONObject getDisk = new JSONObject();
        /*
        <getDisk>
            <catalogID>FtRBZyuboPFCQQYp1SGhPX6c5EWw06DbQ</catalogID>
            <entryShareCatalogID></entryShareCatalogID>
            <filterType>0</filterType>
            <catalogSortType>0</catalogSortType>
            <contentType>0</contentType>
            <contentSortType>0</contentSortType>
            <sortDirection>0</sortDirection>
            <startNumber>-1</startNumber>
            <endNumber></endNumber>
            <catalogType>-1</catalogType>
            <contentSuffix></contentSuffix>
        </getDisk>
        */
        getDisk.put("catalogID", hcyAuth.getAppCatalogID());
        getDisk.put("filterType", 0);
        getDisk.put("catalogSortType", 0);
        getDisk.put("contentType", 0);
        getDisk.put("contentSortType", 0);
        getDisk.put("sortDirection", 0);
        getDisk.put("startNumber", -1);
        getDisk.put("catalogType", -1);


        param.put("getDisk", getDisk);
        JSONObject res = null;
        Object tempRes = getHCYAPICommonFun(hcyAuth, HCYgetdiskURL, param.toJSONString(), true);
        if (checkRes(tempRes, hcyAuth)) {
            res = (JSONObject) tempRes;
        }else{
            log.error("查询个人云文件列表 失败 tempRes: {} openid:{}", tempRes, hcyAuth.getId());
            return;
        }

        /*
        <?xml version="1.0" encoding="UTF-8"?>
        <result resultCode="0">
            <getDiskResult>
                <parentCatalogID>0Q11diXl808e00019700101000000071</parentCatalogID>
                <nodeCount>1</nodeCount>
                <contentList length="1">
                    <contentInfo>
                        <contentID>0Q11diXl808e06920231202110809dbk</contentID>
                        <contentName>newWordsNotebook.json</contentName>
                        <contentSuffix>json</contentSuffix>
                        <contentSize>162</contentSize>
                        <contentDesc></contentDesc>
                        <isShared>false</isShared>
                        <contentType>0</contentType>
                        <contentOrigin>2</contentOrigin>
                        <updateTime>20231202110809</updateTime>
                        <commentCount>0</commentCount>
                        <thumbnailURL></thumbnailURL>
                        <bigthumbnailURL></bigthumbnailURL>
                        <midthumbnailURL></midthumbnailURL>
                        <presentURL>http://download.mcloud.139.com:80/storageWeb/servlet/GetFileByURLServlet?root=/mnt/wfs146&amp;fileid=KMd5f09ded9df592b93c2175429be260eb.json&amp;ct=0&amp;type=2&amp;code=E6591D7113C25EE9AA75BFD36502C7965C655B25C50DFFA1FB0E0067CC5C159D&amp;exp=329&amp;account=MFExMWRpWGw4MDhl&amp;p=0&amp;ui=0Q11diXl808e&amp;ci=0Q11diXl808e06920231202110809dbk&amp;userSiteId=usersite-s&amp;cn=newWordsNotebook&amp;oprChannel=10230036&amp;dom=D962</presentURL>
                        <presentLURL></presentLURL>
                        <presentHURL></presentHURL>
                        <shareDoneeCount>0</shareDoneeCount>
                        <safestate>0</safestate>
                        <transferstate>0</transferstate>
                        <isFocusContent>0</isFocusContent>
                        <uploadTime>20231202110809</uploadTime>
                        <ETagOprType>1</ETagOprType>
                        <openType>0</openType>
                        <auditResult>0</auditResult>
                        <parentCatalogId>0Q11diXl808e03120231129161650n16</parentCatalogId>
                        <channel>10214200</channel>
                        <digest>CE94BA3A3487C0A3C15B5045D31BA9A8</digest>
                        <geoLocFlag>0</geoLocFlag>
                        <version></version>
                        <fileEtag>1842185668306242577</fileEtag>
                        <encryptFlag>0</encryptFlag>
                        <fileVersion>1842185668285308898</fileVersion>
                        <tombstoned>0</tombstoned>
                        <proxyID></proxyID>
                        <moved>0</moved>
                        <owner>13418100840</owner>
                        <modifier>13418100840</modifier>
                        <shareType>0</shareType>
                        <exif>
                            <createTime>19700101000000</createTime>
                        </exif>
                        <isIngested>1</isIngested>
                        <extInfo size="1">
                            <item>
                                <key>uploader</key>
                                <value>13418100840</value>
                            </item>
                        </extInfo>
                        <extProp3></extProp3>
                    </contentInfo>
                </contentList>
                <isCompleted>0</isCompleted>
            </getDiskResult>
        </result>
        {
            "getDiskResult": {
                "parentCatalogID": "0Q11diXl808e00019700101000000071",
                "nodeCount": "1",
                "contentList": {
                    "contentInfo": {
                        "shareDoneeCount": "0",
                        "presentLURL": "",
                        "isIngested": "1",
                        "moved": "0",
                        "modifier": "13418100840",
                        "channel": "10214200",
                        "bigthumbnailURL": "",
                        "transferstate": "0",
                        "safestate": "0",
                        "encryptFlag": "0",
                        "auditResult": "0",
                        "shareType": "0",
                        "presentURL": "http://download.mcloud.139.com:80/storageWeb/servlet/GetFileByURLServlet?root=/mnt/wfs146&fileid=KMd5f09ded9df592b93c2175429be260eb.json&ct=0&type=2&code=E6591D7113C25EE9AA75BFD36502C7965C655B25C50DFFA1FB0E0067CC5C159D&exp=329&account=MFExMWRpWGw4MDhl&p=0&ui=0Q11diXl808e&ci=0Q11diXl808e06920231202110809dbk&userSiteId=usersite-s&cn=newWordsNotebook&oprChannel=10230036&dom=D962",
                        "openType": "0",
                        "extInfo": {
                            "item": {
                                "value": "13418100840",
                                "key": "uploader"
                            }
                        },
                        "fileEtag": "1842185668306242577",
                        "contentSize": "162",
                        "digest": "CE94BA3A3487C0A3C15B5045D31BA9A8",
                        "contentType": "0",
                        "fileVersion": "1842185668285308898",
                        "extProp3": "",
                        "thumbnailURL": "",
                        "isFocusContent": "0",
                        "proxyID": "",
                        "owner": "13418100840",
                        "midthumbnailURL": "",
                        "tombstoned": "0",
                        "contentOrigin": "2",
                        "contentID": "0Q11diXl808e06920231202110809dbk",
                        "updateTime": "20231202110809",
                        "ETagOprType": "1",
                        "contentDesc": "",
                        "uploadTime": "20231202110809",
                        "version": "",
                        "contentName": "newWordsNotebook.json",
                        "commentCount": "0",
                        "parentCatalogId": "0Q11diXl808e03120231129161650n16",
                        "presentHURL": "",
                        "geoLocFlag": "0",
                        "isShared": "false",
                        "contentSuffix": "json",
                        "exif": {
                            "createTime": "19700101000000"
                        }
                    }
                },
                "isCompleted": "0"
            }
        }
        */
        JSONObject getDiskResult = res.getJSONObject("getDiskResult");
        JSONObject contentList = getDiskResult.getJSONObject("contentList");
        Object contentInfo = contentList.get("contentInfo");
        if (contentInfo instanceof Map){
            //是Map, 只有一个文件 , 检查是否是 "生词本" "newWordsNotebook.json"
            JSONObject contentInfoOB = new JSONObject((Map)contentInfo);
            String contentName = contentInfoOB.getString("contentName");
            //取内容ID保存
            String contentID = contentInfoOB.getString("contentID");
            if(contentName.equalsIgnoreCase(DeviceSanWordService.newWordsNotebookName)){
                hcyAuth.setContentID(contentID);
            }else if (contentName.equalsIgnoreCase(DeviceSanWordService.scanWordNotebookName)){
                //取内容ID保存
                hcyAuth.setScanContentID(contentID);
            }
            hcyAuth = this.save(hcyAuth);
            log.debug("保存 contentID: {} 文件内容ID contentName:{} 成功 openid:{}", contentID, contentName, hcyAuth.getId());
        }else if (contentInfo instanceof ArrayList) {
            //是Array, 有多个文件 ,遍历检查 文件
            JSONArray contentArr = new JSONArray((ArrayList)contentInfo);
            boolean shouldSave = false;
            for (int i = 0; i < contentArr.size(); i++) {
                JSONObject item = contentArr.getJSONObject(i);
                String contentName = item.getString("contentName");
                //取内容ID保存
                String contentID = item.getString("contentID");
                if(contentName.equalsIgnoreCase(DeviceSanWordService.newWordsNotebookName)){
                    hcyAuth.setContentID(contentID);
                    shouldSave = true;
                    log.debug("保存 contentID: {} newWordsNotebookName 文件内容ID contentName:{} 成功 openid:{}", contentID, contentName, hcyAuth.getId());
                }else if (contentName.equalsIgnoreCase(DeviceSanWordService.scanWordNotebookName)){
                    //取内容ID保存
                    hcyAuth.setScanContentID(contentID);
                    shouldSave = true;
                    log.debug("保存 contentID: {} scanWordNotebookName 文件内容ID contentName:{} 成功 openid:{}", contentID, contentName, hcyAuth.getId());
                }
            }
            if(!shouldSave){
                this.save(hcyAuth);
            }
        }
    }

    // 上传文件

    public boolean  uploadFileWithObject(HCYAuth hcyAuth, String fileJSONStr, String contentName, int type){
        byte[] fileBytes = fileJSONStr.getBytes(StandardCharsets.UTF_8);
        /*
        <?xml version="1.0" encoding="utf-8"?>
        <pcUploadFileRequest>
          <totalSize>1590</totalSize>
          <parentCatalogID>应用目录ID</parentCatalogID>
          <uploadContentList length="1">
            <uploadContentInfo>
              <contentName>outLineVoice.amr</contentName>
              <contentSize>1590</contentSize>
            </uploadContentInfo>
          </uploadContentList>
        </pcUploadFileRequest>

        注意这个uploadContentList 的属性一定要加上  length="1"
        */
        JSONObject param = new JSONObject();
        JSONObject pcUploadFileRequest = new JSONObject();
        pcUploadFileRequest.put("parentCatalogID", hcyAuth.getAppCatalogID());
        pcUploadFileRequest.put("totalSize", fileBytes.length);

        JSONObject uploadContentList = new JSONObject();
        JSONObject uploadContentInfo = new JSONObject();
        uploadContentInfo.put("contentName", contentName);
        uploadContentInfo.put("contentSize", fileBytes.length);
        uploadContentList.put("uploadContentInfo", uploadContentInfo);
        pcUploadFileRequest.put("uploadContentList", uploadContentList);
        param.put("pcUploadFileRequest", pcUploadFileRequest);

        //生成个替换一下
        Map<String, String> xmlReplaceMap = new HashMap<>();
        xmlReplaceMap.put("<uploadContentList>","<uploadContentList length=\"1\">");
        xmlReplaceMap.put("<Request>","");
        xmlReplaceMap.put("</Request>","");

        //得到上传的地址
        JSONObject resOB = null;
        Object tempRes = getHCYAPICommonFun(hcyAuth, HCYuploadFileURL, param.toJSONString(), xmlReplaceMap);
        if (checkRes(tempRes, hcyAuth)) {
            resOB = (JSONObject) tempRes;
        }else{
            log.error("上传文件错误:contentName:{} openid:{} phone:{}", contentName, hcyAuth.getId(), hcyAuth.getPhone());
            return false;
        }

        /*
        <?xml version="1.0" encoding="UTF-8"?>
        <result  resultCode="0">
            <uploadResult>
                <uploadTaskID>KB0Q11diXl808e22417u2lHCkNn</uploadTaskID>
                <redirectionUrl>http://upload.mcloud.139.com:80/storageWeb/servlet/uploadFileServlet?uploadCode=S0IwUTExZGlYbDgwOGUyMjQxN3UybEhDa05u&amp;txType=0&amp;oprChannel=10230036&amp;dom=D961&amp;rate=0</redirectionUrl>
                <newContentIDList  length="1">
                    <newContent>
                        <contentID>0Q11diXl808e06920231202144445jvv</contentID>
                        <contentName>outLineVoice.amr</contentName>
                        <isNeedUpload>1</isNeedUpload>
                        <fileEtag>1842240175971113056</fileEtag>
                        <overridenFlag>0</overridenFlag>
                        <fileVersion>1842240175971113057</fileVersion>
                    </newContent>
                </newContentIDList>
            </uploadResult>
        </result>
        //转后
        {
            "uploadResult": {
                "uploadTaskID": "KB0Q11diXl808e22417u2lHCkNn",
                "redirectionUrl": "http://upload.mcloud.139.com:80/storageWeb/servlet/uploadFileServlet?uploadCode=S0IwUTExZGlYbDgwOGUyMjQxN3UybEhDa05u&txType=0&oprChannel=10230036&dom=D961&rate=0",
                "newContentIDList": {
                    "newContent": {
                        "fileEtag": "1842240175971113056",
                        "overridenFlag": "0",
                        "contentID": "0Q11diXl808e06920231202144445jvv",
                        "isNeedUpload": "1",
                        "fileVersion": "1842240175971113057",
                        "contentName": "outLineVoice.amr"
                    }
                }
            }
        }
        */
        JSONObject uploadResult = resOB.getJSONObject("uploadResult");
        String uploadTaskID = uploadResult.getString("uploadTaskID");
        String redirectionUrl = uploadResult.getString("redirectionUrl");
        String contentID = uploadResult.getJSONObject("newContentIDList").getJSONObject("newContent").getString("contentID");
        //根据 redirectionUrl 和 uploadTaskID 上传

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "");
        headers.put("Content-type", "application/octet-stream"+";"+"name="+contentName);
        headers.put("Range", "bytes=0-"+fileBytes.length);
//        headers.put("Content-Length", ""+fileBytes.length);
        headers.put("contentSize", ""+fileBytes.length);
        headers.put("UploadtaskID", uploadTaskID);
        String result = HttpReq.sendPostWithByteArr(redirectionUrl, fileBytes, headers);
        if(result != null && result.contains("<resultCode>0</resultCode>")){
            //上传成功, 保存
            if (type==1) {
                //生词本
                hcyAuth.setContentID(contentID);
            } else if (type==2) {
                //扫描本
                hcyAuth.setScanContentID(contentID);
            } else{
                //type 不对
                return false;
            }
            hcyAuth.setUpdateDate(new Date());
            this.save(hcyAuth);
            return true;
        }else{
            log.debug("上传文件失败:{} redirectionUrl:{}", result, redirectionUrl);
            return false;
        }

    }

    /**
     * 下载文件
     * @param hcyAuth
     * @param contentID 文件ID
     * @param type 文件类型 1:生词本 2:扫描本
     */
    public JSONObject getDownloadFile(HCYAuth hcyAuth, String contentID, int type){
        JSONObject param = new JSONObject();
        JSONObject downloadRequest = new JSONObject();
        downloadRequest.put("contentID", contentID);
        param.put("downloadRequest", downloadRequest);
        JSONObject res = null;
        Object tempRes = getHCYAPICommonFun(hcyAuth, HCYdownloadFileURL, param.toJSONString(), true);
        if (checkRes(tempRes, hcyAuth)) {
            res = (JSONObject) tempRes;
        }else{
            log.error("下载文件错误:contentID:{} openid:{} phone:{}", contentID, hcyAuth.getId(), hcyAuth.getPhone());
            return null;
        }
        /*
        <?xml version="1.0" encoding="UTF-8"?>
        <result  resultCode="0">
            <String>http://download.mcloud.139.com:80/storageWeb/servlet/downloadServlet?code=S00wUTExZGlYbDgwOGU4MzIxN3UybEdlUElI&amp;un=D0FA91881019A1D1BAF33E50CA8DF2E4A8EE71AE62420D6CE25A9B723D81980E&amp;dom=D962&amp;rate=0&amp;txType=0</String>
        </result>
        */
        String downloadURL = res.getString("String");
        String result = HttpReq.sendGet(downloadURL);
        return JSONObject.parseObject(result);
    }



    public Object getHCYAPICommonFun(HCYAuth authOB, String url, String paramStr, Map<String, String>xmlReplaceMap){
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put("appid", this.getAppID(authOB));
            headers.put("secretKey", this.getAppSecret(authOB));
            headers.put("accessToken", authOB.getAccesstoken());
            headers.put("deviceid", authOB.getId());
            headers.put("channelid", HCYChannelId);
            headers.put("content-type","application/xml");
            if (paramStr != null) {
                paramStr = NewXMLUtil.createXmlByMap(JSONObject.parseObject(paramStr));
                for (String itemKey :xmlReplaceMap.keySet()) {
                    paramStr = paramStr.replaceAll(itemKey, xmlReplaceMap.get(itemKey));
                }
            }
            return getHCYAPICommonFun(headers, url, paramStr);
        }catch (Exception e){
            log.error("移动云盘 HTTP接口 的公用请求方法 失败 url:"+url, e);
        }
        return null;
    }


    /**
     * 调用 移动云盘 HTTP接口 的公用请求方法
     * @param authOB
     * @param url
     * @param paramStr
     * @param isXML
     * @return
     */
    public Object getHCYAPICommonFun(HCYAuth authOB, String url, String paramStr, boolean isXML){
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put("appid", this.getAppID(authOB));
            headers.put("secretKey", this.getAppSecret(authOB));
            headers.put("accessToken", authOB.getAccesstoken());
            headers.put("deviceid", authOB.getId());
            headers.put("channelid", HCYChannelId);

            if (isXML && paramStr != null) {
                headers.put("content-type","application/xml");
                paramStr = NewXMLUtil.createXmlByMap(JSONObject.parseObject(paramStr));
            }
            return getHCYAPICommonFun(headers, url, paramStr);
        }catch (Exception e){
            log.error("移动云盘 HTTP接口 的公用请求方法 失败 url:"+url, e);
        }
        return null;
    }
    /**
     * 调用 移动云盘 HTTP接口 的公用请求方法
     */
    public Object getHCYAPICommonFun(Map<String, String> headers, String url, String paramStr){
        try{
            log.debug("header:{} url:{} 请求参数:{}",headers, url, paramStr);
            String result = HttpReq.sendPostJson(url, paramStr, headers);
            JSONObject resOB = XMLUtil.xmlToJSONObject(result);
            if(resOB.size() != 0){
                //有内容
                return resOB;
            }else{
                //无内容, 一般为报错
                //<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                //"<result  resultCode=\"200000501\" desc=\"[501225|F9E37BA46CA04EF3B03917FCA5381B8F]Failed to invoke the service.0[NDA(100590)][Flag:F9E37BA46CA04EF3B03917FCA5381B8F]\">\n" +
                //"</result>
                log.error("移动云盘 HTTP接口 的公用请求方法 失败 url:{} paramStr:{} result:{}", url,paramStr, result);
                return null;
            }
        }catch (Exception e){
            //200000401
            log.error("移动云盘 HTTP接口 的公用请求方法 失败 url:"+url + "paramStr:"+paramStr, e);
        }
        return null;
    }


    public boolean checkRes(Object tempRes, HCYAuth hcyAuth){
        if(tempRes instanceof Integer){
            switch (((Integer) tempRes).intValue()) {
                case -1: // token失效
                    hcyAuth.setAccesstoken(null);
                    hcyAuth.setAccesstoken_expiry(null);
                    hcyAuth.setAccesstoken_update(null);
                    break;
                case -2: // 目录被删
                    //可能是应用目录被流程以外的操作 意外删除了
                    //清除 hcyAuth 的 appCatalogID contentID sanContentID
                    hcyAuth.setAppCatalogID(null);
                    break;
                case -3: // 找不到生词本 内容ID
                    hcyAuth.setContentID(null);
                    break;
                case -4: // 找不到扫描本 内容ID
                    hcyAuth.setScanContentID(null);
                    break;
            }
            this.save(hcyAuth);
            return false;
        }else{
            return true;
        }

    }


    public boolean checkPhone(String phone) {
        if (phone == null) {
            return false;
        }
        String regex = "^((13[0-9])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\\d{8}$";
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(phone);
        return m.matches();
    }


}
